ES6 Event Emitter
rendezvous with cassidoo issue #132
by Jesse Rogers
HTML
<div id="wrapper">
<strong id="message">Don't do it. Don't press W.</strong>
</div>
CSS
* {
box-sizing: border-box;
font-family: monospace;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
#wrapper {
background: #212121;
height: 100%;
left: 0;
position: fixed;
top: 0;
width: 100%;
}
#wrapper strong {
color: yellow;
left: 50%;
margin: 0;
text-align: center;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
}
#wrapper.omg {
background: #ed4e39
}
#wrapper.omg strong {
color: white;
}
JavaScript
// rendezvous with cassidoo issue #132
// Write an event emitter that has three methods: on, emit, and removeListener.
// The `on` function takes in an event name and a callback function, the `emit`
// function takes in an event name and data (which will be passed to the
// associated callback), and `removeListener` takes in an event name and a callback
// to remove from that event.
class EventEmitter {
constructor() {
this.events = new Map();
}
/**
* @param eventName: string
* @param callback: (args: any[]) => void
*/
on(eventName, callback) {
// check for existing listeners on this event name
const callbacks = this.events.get(eventName);
// if existing listeners, just add to the list
if (callbacks) {
callbacks.push(callback);
} else {
// otherwise, create a new array of listeners
// for the event name
this.events.set(eventName, callback ? [callback] : []);
}
}
/**
* @param eventName: string
* @param args: any[]
*/
emit(eventName, args = []) {
// retrieve all registered callbacks for the event name
const callbacks = this.events.get(eventName);
// no callback(s), exit early
if (!callbacks) {
console.error('No listener for ' + eventName);
return;
}
// if contextual arguments supplied, pass them to callbacks
if (callbacks && args) {
callbacks.forEach(callback => callback(...args));
} else {
// no data/context, just fire the method
callbacks.forEach(callback => callback());
}
}
/**
* @param eventName: string
* @param callback: (args: any[]) => void
*/
removeListener(eventName, callback) {
// if nothing to delete, do nothing
if (!this.events.get(eventName)) {
return;
}
// remove event from map
this.events.delete(eventName);
// dispose of callback function
if (callback) {
callback();
}
}
}
// instantiate emitter instance
const emitter = new EventEmitter();
//...